<?php
declare (strict_types=1);

namespace app\admin\middleware;

use Closure;
use think\Request;
use think\Response;
use app\common\utils\JwtUtils;
use app\common\enum\SystemEnum;
use app\common\trait\ResultTrait;
use app\common\cache\system\UserCache;

class AuthMiddleware
{
    /**
     * 引入接口统一返回快捷操作
     */
    use ResultTrait;

    /**
     * 处理请求
     *
     * @param Request $request
     * @param Closure $next
     * @return Response
     */
    public function handle(Request $request, Closure $next): Response
    {
        $menu_url = $request->baseUrl();//获取当前访问的URL
        //验证菜单是否需要登录后访问
        if (!in_array($menu_url, get_not_login_url())) {
            $token = $request->header(env('token.system_token_name', 'X-System-Token'));//通过请求头获取设置的TOKEN凭证
            if (empty($token)) {
                return $this->error(SystemEnum::TOKEN_NOT_EXIST);//TOKEN为空返回错误
            }
            $system_config = get_sys_config('', 'token');//获取系统TOKEN组配置
            $token_info    = JwtUtils::verifyToken($token, $system_config['token_admin_key']);//验证TOKEN,成功返回自定义信息,失败返回错误码
            if (is_int($token_info)) {
                return $this->error($token_info);//TOKEN验证失败,返回错误
            }
            $user_info = UserCache::get($token_info['system_user_id']);//获取登录后的用户信息
            if (empty($user_info)) {
                return $this->error(SystemEnum::LOGIN_TIMEOUT);//如果缓存不存在则登录超时错误
            }
            $site_config = get_sys_config('site_repeat_login');//获取后台单点登录设置
            if ($site_config == 'true' && $user_info['token'] != $token) {
                return $this->error(SystemEnum::REPEAT_LOGIN);//管理员已在其他设备登录请重新登录
            }
            //用户如果不是超级管理员则验证账户权限
            if ($user_info['is_super'] === 0) {
                $auth_url = get_menu_auth_url($user_info['id'], $user_info['role_ids']);
                if (!in_array($menu_url, $auth_url)) {
                    return $this->error(SystemEnum::NO_PERMISSION);//用户没有操作权限错误
                }
            }
            $request->token_info      = $token_info;//传递TOKEN自定义参数
            $request->cache_user_info = $user_info;//传递已登录的用户缓存信息
        }

        return $next($request);//当前菜单无需登录进入
    }
}
